﻿--===========--
--== Table ==--
--===========--
	
	-- Ashes, Ashes ... Blackhand achievement!
	function AshesCount()
	
		if not AshesCountReady then
			
			members = { { Unit = "player" } }
			member = { { AshesCount = 0 } }
			
			if IsInRaid() then
				group = "raid"
	   		elseif IsInGroup() then
	   			group = "party"
			end
			
			for i = 1, GetNumGroupMembers() do
				table.insert( members,{ Unit = group..i } )
				table.insert( member,{ AshesCount = 0 } )
			end
			
			if UnitAffectingCombat("player") then AshesCountReady = true else AshesCountReady = false end
			
		end
		
	for i = 1, 4 do
	if UnitExists("boss"..i) then
	if GetUnitID("boss"..i) == 77325 then -- Blackhand
		
		Ashes = 0
		AshesID = 163324
		
	    	for i = 1, #members do
	        	if UnitDebuffID(members[i].Unit,AshesID) then
					member[i].AshesCount = select(4,UnitDebuffID(members[i].Unit,AshesID)) or 1
	     	        end
			Ashes = Ashes + member[i].AshesCount
	     	end
		
		if Ashes ~= 0 then print_Log("Ashes collected: "..Ashes) end
		
	end
	end
	end
	
	end
	
	Food = nil
	Food = {
		160903, 160901, 160898, 160896, 160894,
		160890, 160887, 160884, 160725, 160598,
		160599, 160881, 160880, 160879, 160877,
		160872, 160869, 160865, 160846, 160840,
		160830, 160794, 160777, 160727, 160723,
		160506
	}
	
	TrinketsBuffID = {
		--
		126268,	126534, 126552, 126679, 126683, 126690, 126702, 126706, 126708, 
		127914, 127924, 127926, 127967, 133631, 146251,	155447,	157136,	162914,
		162918, 162920, 165485, 165531, 165532, 165534, 165535,	165542, 165543, 
		165821, 165825, 165838, 165840, 170397,
		-- Agi DPS:
		176984, -- Blackheart Enforcer's Medallion
		176939, -- Formidable Jar of Doom
		177597, -- Lucky Double-Sided Coin
		162915, -- Skull of War
		177038, -- Scales of Doom
		177035, -- Meaty Dragonspine Trophy
		176878, -- Beating Heart of the Mountain
		177067, -- Humming Blackiron Trigger
		183926, -- Malicious Censer
	}
	
	TickingEbonDetonator = nil
	TickingEbonDetonator = {
		105114,	-- 528 Raid Finder
		104865,	-- 540 Flexible
		102311,	-- 553 Normal
		105363,	-- 559 Normal Warforged
		104616,	-- 566 Heroic
		105612	-- 572 Heroic Warforged
	}
	
	PetBasicAttacks = nil
	PetBasicAttacks = {
		17253, -- Bite
		16827, -- Claw
		49966, -- Smack
	}
	
--=========--
--== WWF ==--
--=========--
	
	print_Log = nil
	function print_Log(text)
		text = text or "text"
		if not lasttext then lasttext = "lasttext" end
		if text ~= lasttext and text ~= "text" then lasttext = text print(text) end
	end
	
	ExecuteAoEspell = nil
	function ExecuteAoEspell()
		if SpellIsTargeting() then
	        	CameraOrSelectOrMoveStart()
	        	CameraOrSelectOrMoveStop()
			return true
		end
	end
	
	UseTrinkets = nil
	function UseTrinkets()
		UseInventoryItem(13)
		UseInventoryItem(14)
	end
	
	TranquilizingShot = nil
	function TranquilizingShot(tranqtar)
		tranqtar = tranqtar or "target"
		local i = 1
		local Buff,_,_,_,BuffType = UnitAura(tranqtar, i)
		while Buff do
			if BuffType == "" or BuffType == "Magic" or BuffType == "Enrage" then return true end
			i = i + 1
			Buff,_,_,_,BuffType = UnitAura(tranqtar, i)
		end
	end
	
	PetInRange = nil
	function PetInRange(unit)
		if UnitExists("pet") and UnitExists(unit) then
			for i = 1, #PetBasicAttacks do if IsSpellInRange(GetSpellInfo(PetBasicAttacks[i]),unit) == 1 then return true end end
		end
	end
	
	NBBL = nil
	function NBBL() -- Monk's "Nimble brew black list"
		if UnitDebuffID("player", 142913) then
			return true
		else
			return false
		end
	end
	
	SHBL = nil
	function SHBL() -- self heal black list
		if UnitDebuffID("player", 137633) -- Tortos: Crystal Shell
		or (UnitDebuffID("player", 142861) and (UnitDebuffID("player", 142864) or UnitDebuffID("player", 142865))) -- Malkorok: Ancient Miasma and Ancient Barrier or Strong Ancient Barrier
		then
			return true
		else
			return false
		end
	end
	
	HaveGlyph = nil
	function HaveGlyph(id)
		
		for i = 1, GetNumGlyphSockets() do
			if select(4, GetGlyphSocketInfo(i)) == id then return true end
		end
		
		return false
		
	end
	
	GetSpellCD = nil
	function GetSpellCD(SpellID)
		
		if GetSpellCooldown(GetSpellInfo(SpellID)) == nil
		or GetSpellCooldown(GetSpellInfo(SpellID)) == 0 then
			return 0
		else	
			local Start, Duration = GetSpellCooldown(GetSpellInfo(SpellID))
			if Duration ~= 0 then return Start + Duration - GetTime() else return 0 end
		end
		
	end
	
	AggroCheck = nil
	function AggroCheck(unit1, unit2)
		
		if UnitExists(unit1) and UnitExists(unit2) then
			if not UnitThreatSituation(unit1, unit2) then
				return false
			elseif UnitThreatSituation(unit1, unit2) >= 2 then
				return true
			else
				return false
			end
		else
			return false
		end
		
	end
	
	CTT = nil
	function CTT()
		
		local t = 1
		local TrinketsTimers = {0, 0}
		
		for i = 1, #TrinketsBuffID do
			if UnitBuffID("player", TrinketsBuffID[i]) then
				TrinketsTimers[t] = select(7,UnitBuffID("player", TrinketsBuffID[i])) - GetTime()
				if t == 1 then t = 2 end
			end
		end
		
		return TrinketsTimers[1], TrinketsTimers[2]
		
	end
	
	CBLT = nil
	function CBLT()
		
		local BLTimer = 0
		local BLid = {
					 	2825, 	--	Bloodlust
					 	32182,	--	Heroism
					 	80353,	--	Time Warp
					 	90355	--	Ancient Hysteria
					 }
		
		for i = 1, #BLid do
			if UnitBuffID("player", BLid[i]) then
				BLTimer = select(7, UnitBuffID("player", BLid[i])) - GetTime()
			end
		end
		
		return BLTimer
		
	end
	
	GetUnitID = nil
	function GetUnitID(unit)
		if UnitExists(unit) and not UnitIsDead(unit) then
			a = 0
			b = 0
			n = 0
			for i = 1, 40 do
				local nSymbol = UnitGUID(unit):sub(i,i),10
				if nSymbol == "-" then n = n + 1 end
				if n == 5 and a == 0 then a = i + 1 end
				if n == 6 and b == 0 then b = i - 1 end
				if a > 0 and b > 0 then return tonumber(UnitGUID(unit):sub(a,b),10) end
			end
			return 0
		else
			return 0
		end
	end
	
	InstanceDifficulty = nil
	function InstanceDifficulty()
		
		ID = select(3, GetInstanceInfo())
		diff = "OutOfInstance"
		if ID == 0 then		diff = "OutOfInstance"
		elseif ID == 1 then	diff = "Dungeon_Normal"
		elseif ID == 2 then	diff = "Dungeon_Heroic"
		elseif ID == 3 then	diff = "Raid_Normal_10ppl"
		elseif ID == 4 then	diff = "Raid_Normal_25ppl"
		elseif ID == 5 then	diff = "Raid_Heroic_10ppl"
		elseif ID == 6 then	diff = "Raid_Heroic_25ppl"
		elseif ID == 7 then	diff = "Raid_LFR_25ppl"
		elseif ID == 8 then	diff = "Dungeon_Challenge"
		elseif ID == 9 then	diff = "Raid_40ppl"
		elseif ID == 10 then	diff = "NotUsed"
		elseif ID == 11 then	diff = "Scenario_Heroic"
		elseif ID == 12 then	diff = "Scenario_Normal"
		elseif ID == 13 then	diff = "NotUsed"
		elseif ID == 14 then	diff = "Raid_Normal"
		elseif ID == 15 then	diff = "Raid_Heroic"
		elseif ID == 16 then	diff = "Raid_Mythic"
		elseif ID == 17 then	diff = "Raid_LFR"
		elseif ID == 18 then	diff = "Raid_Event_40ppl"
		elseif ID == 19 then	diff = "Dungeon_Event_90lvl"
		elseif ID == 20 then	diff = "Scenario_Event_25ppl"
		elseif ID == 21 then	diff = "NotUsed"
		elseif ID == 22 then	diff = "NotUsed"
		elseif ID == 23 then	diff = "Dungeon_Mythic"
		elseif ID == 24 then	diff = "Dungeon_Timewalker"
		end
		
		return diff
		
	end
	
	Range = nil
	function Range(unit1,unit2)
		
		if UnitIsUnit(unit1,unit2)
		or not UnitExists(unit1)
		or not UnitExists(unit2)
		then return 999 end
		
		local x1,y1 = GetPlayerMapPosition(unit1)
		local x2,y2 = GetPlayerMapPosition(unit2)
		
		if x1 <= 0 and y1 <= 0 then return nil end
		if x2 <= 0 and y2 <= 0 then return nil end
	    
		local _,_,_,d,e,f,g,_,_,_ = GetAreaMapInfo(GetCurrentMapAreaID())
		
		local width = (d - e)
		local height = (f - g)
		
		local dx = (x2 - x1) * width
		local dy = (y2 - y1) * height
		
		return sqrt(dx*dx + dy*dy) -- distance in yard
		
	end
	
	RangeCheck = nil
	function RangeCheck(dist)
		
		if IsInRaid() then group = "raid"
		elseif IsInGroup() then group = "party"
		end
		
		for i = 1, GetNumGroupMembers() do
			Distance = Range("player",group..i)
	   		if Distance ~= nil and Distance <= dist then return true end
		end
		
		return false
		
	end
	
	CancelBuffByID = nil
	function CancelBuffByID(ID)
		local index = 1
		while UnitAura("player", index, "HELPFUL") do
			if select(11, UnitAura("player", index, "HELPFUL")) == ID then
				CancelUnitBuff('player', index, 'HELPFUL')
				return
			end
			index = index + 1
		end
	end
	
	IsActiveTrinket = nil
	function IsActiveTrinket(table)
		
		local Trinket1 = GetInventoryItemID("player", 13)
		local Trinket2 = GetInventoryItemID("player", 14)
		local TrinketID = table or {"empty"}
		
		for i = 1, #TrinketID do
			if Trinket1 == TrinketID[i] or Trinket2 == TrinketID[i] then
				return true
			end
		end
		
		return false
		
	end
	
	FocusNPC = nil
	function FocusNPC(table)
		
		local name, realm = UnitName("target")
		if realm == nil then
			if name == nil then
				lasttargetname = "none"
			else lasttargetname = name end
		else
			lasttargetname = name.."-"..realm
		end
		
		local NPC_Table = table or {"empty"}
		
		for i = 1, #NPC_Table do
			TargetUnit(NPC_Table[i] , true)
			if UnitExists("target") then
				if UnitName("target") == NPC_Table[i] then
					FocusUnit('target')
					if lasttargetname == "none" then
						ClearTarget()
					else
						RunMacroText("/targetexact "..lasttargetname)
					end
					return true
				end
			end
		end
		
	end
	
	KoraghSP = nil
	function KoraghSP() -- buff id 156803
	if UnitExists("boss1") then
		if GetUnitID("boss1") == 79015 then -- [Ko'ragh] <[Breaker of Magic]>
			Mode = InstanceDifficulty()
			if Mode == "Raid_LFR" then
				NullificationBarrier = {	 -- Absorb\raid size:
							2412540, -- 10
							2665857,
							2919173,
							3172490,
							3425807,
							3679124,
							3932440,
							4185757,
							4439074,
							4692390,
							4945707, -- 20
							5199024,
							5452340,
							5705657,
							5958974,
							6212291,
							6465607,
							6718924,
							6972241,
							7225557,
							7478874 -- 30
							}
			elseif Mode == "Raid_Normal" then
				NullificationBarrier = {
							4020890, -- 10
							4443083,
							4865277,
							5287470,
							5709664,
							6131857,
							6554051,
							6976244,
							7398438,
							7820631,
							8242825, -- 20
							8665018,
							9087211,
							9509405,
							9931598,
							10353792,
							10775985,
							11198179,
							11620372,
							12042566,
							12464759 -- 30
							}
			elseif Mode == "Raid_Heroic" then
				NullificationBarrier = {
							5026112, -- 10
							5553854,
							6081596,
							6609337,
							7137079,
							7664821,
							8192563,
							8720304,
							9248046,
							9775788,
							10303530, -- 20
							10831271,
							11359013,
							11886755,
							12414497,
							12942238,
							13469980,
							13997722,
							14525464,
							15053205,
							15580947 -- 30
							}
			elseif Mode == "Raid_Mythic" then
				NullificationBarrier = {13394589}
			end
			if Mode ~= "Raid_Mythic" and GetNumGroupMembers() >= 10 then
				if GetNumGroupMembers() > 30 then NumGroupMembers = 21 else NumGroupMembers = GetNumGroupMembers() - 9 end
			else
				NumGroupMembers = 1
			end
			KoraghAbsorb = UnitGetTotalAbsorbs("boss1") or 0
			if KoraghAbsorb > NullificationBarrier[NumGroupMembers] then KoraghAbsorb = NullificationBarrier[NumGroupMembers] end
			return KoraghAbsorb/NullificationBarrier[NumGroupMembers]*100, KoraghAbsorb, NullificationBarrier[NumGroupMembers]
		end
		return 0, 0, 0
	end
		return 0, 0, 0
	end
	
	SLASH_GETTARGETID1 = "/GetTargetID"
	function SlashCmdList.GETTARGETID()
		print("ID of your current target is '"..GetUnitID("target").."'")
	end
	
--============--
--== Xelper ==--
--============--
	
	IsChanneling = nil
	function IsChanneling()
		
		local _, _, _, _, _, playerChanneling = UnitChannelInfo("player")
		local isPlayerChanneling = false
		
		if playerChanneling ~= nil then
			local currentTime = GetTime() * 1000
			if (playerChanneling - currentTime) > 100 then
				isPlayerChanneling = true
			end
		end
		
		return isPlayerChanneling
		
	end
	
	IsCasting = nil
	function IsCasting()
		
		local _, _, _, _, _, playerCasting = UnitCastingInfo("player")
		local isPlayerCasting = false
		
		if playerCasting ~= nil then
			local currentTime = GetTime() * 1000
			if (playerCasting - currentTime) > 100 then
				isPlayerCasting = true
			end
		end
		
		return isPlayerCasting
		
	end
	
	IsCastingSpell = nil
	function IsCastingSpell(spellID, tar)
		
		local tar = tar or "player"
		local spellName = GetSpellInfo(spellID)
		local spellCasting = UnitCastingInfo(tar)
		
		if not spellCasting then spellCasting = UnitChannelInfo(tar) end
		
		if spellCasting == spellName then
			return true
		else
			return false
		end
	end
	
	GCDSpellID = nil
	function GCDSpellID()
		
		local _, playerClass = UnitClass("player")
		
		if playerClass == "DEATHKNIGHT" then
			return 52375
		elseif playerClass == "DRUID" then
			return 774
		elseif playerClass == "HUNTER" then
			return 56641
		elseif playerClass == "MAGE" then
			return 1459
		elseif playerClass == "PALADIN" then
			return 85256
		elseif playerClass == "PRIEST" then
			return 2050
		elseif playerClass == "ROGUE" then
			return 1752
		elseif playerClass == "SHAMAN" then
			return 45284
		elseif playerClass == "WARLOCK" then
			return 980
		elseif playerClass == "WARRIOR" then
			return 1715
		elseif playerClass == "MONK" then
			return 100780
		else
			return 0
		end
		
	end
	
	IsSpellAvailable = nil
	function IsSpellAvailable(spellID)
		
		if not IsPlayerSpell(spellID) then return false end
		
		local gcdSpell = GCDSpellID()
		local gcdStartTime, gcdDuration = GetSpellCooldown(gcdSpell)
		local spellStartTime, spellDuration = GetSpellCooldown(spellID)
		local spellUsable = IsUsableSpell(spellID)
		local spellAvailable = false
		local SpellAvailableTime = 0.125
		
		if spellUsable then
			if spellStartTime ~= nil and gcdStartTime ~= nil then
				local spellTimeLeft = GetSpellCD(spellID)
				local gcdTimeLeft = GetSpellCD(gcdSpell)
				if gcdTimeLeft <= 0 then
					--Our GCD spell is not on CD.
					if spellTimeLeft <= SpellAvailableTime then
						--spell will be off CD within 50ms.
						spellAvailable = true
					end
				else
					--Our GCD spell is on CD.
					if spellTimeLeft <= gcdTimeLeft + SpellAvailableTime then
						--spell time left is less than GCD time left + 50ms.
						spellAvailable = true
					end
				end
			end
		end
		
		return spellAvailable
		
	end
	
	UnitBuffID = nil
	function UnitBuffID(unit, spellID, filter)
		
		local spellName = GetSpellInfo(spellID)
		if filter == nil then
			return UnitBuff(unit, spellName)
		else
			local exactSearch = strfind(strupper(filter), "EXACT")
			local playerSearch = strfind(strupper(filter), "PLAYER")
			
			if exactSearch then
				--using the index does not support filter.
				for i=1,40 do
					local _, _, _, _, _, _, _, buffCaster, _, _, buffSpellID = UnitBuff(unit, i)
					if buffSpellID ~= nil then
						if buffSpellID == spellID then
							if (not playerSearch) or (playerSearch and (buffCaster == "player")) then
								return UnitBuff(unit, i)
							end
						end
					else
						return nil
					end
				end
			else
				--just pass the filter to UnitBuff and return.
				return UnitBuff(unit, spellName, nil, filter)
			end
		end
		
	end
	
	UnitDebuffID = nil
	function UnitDebuffID(unit, spellID, filter)
		
		local spellName = GetSpellInfo(spellID)
		if filter == nil then
			return UnitDebuff(unit, spellName)
		else
			local exactSearch = strfind(strupper(filter), "EXACT")
			local playerSearch = strfind(strupper(filter), "PLAYER")
			
			if exactSearch then
				--using the index does not support filter.
				for i=1,40 do
					local _, _, _, _, _, _, _, buffCaster, _, _, buffSpellID = UnitDebuff(unit, i)
					if buffSpellID ~= nil then
						if buffSpellID == spellID then
							if (not playerSearch) or (playerSearch and (buffCaster == "player")) then
								return UnitDebuff(unit, i)
							end
						end
					else
						return nil
					end
				end
			else
				--just pass the filter to UnitDebuff and return.
				return UnitDebuff(unit, spellName, nil, filter)
			end
		end
		
	end
	
	RegisterMovement = nil
	function RegisterMovement(elapsed)
		
		local playerMovementSpeed = GetUnitSpeed("player")
		
		if not CurrentMovingTime then CurrentMovingTime = 0 end
		if not CurrentStationaryTime then CurrentStationaryTime = 0 end
		if not ResetMovementTime then ResetMovementTime = 0.5 end
		
		if playerMovementSpeed ~= 0 then
			CurrentMovingTime = CurrentMovingTime + elapsed
			CurrentStationaryTime = 0
		else
			if CurrentStationaryTime < ResetMovementTime then
				CurrentStationaryTime = CurrentStationaryTime + elapsed
			end
			if CurrentStationaryTime > ResetMovementTime then
				CurrentMovingTime = 0
			end
		end
		
	end
	
	IsMoving = nil
	function IsMoving(seconds)
		
		if not seconds then seconds = 1 end
		if not CurrentMovingTime then CurrentMovingTime = 0 end
		
		local MoltenFeathers = UnitBuffID("player", 98767)
--		local AspectOfTheFox = UnitBuffID("player", 172106) -- Patch 6.2.0: removed from the game.
		
		if MoltenFeathers or CurrentMovingTime < seconds then
			return false
		else
			return true
		end
		 
	end
	
--===============================--
--== Sheuron Healing Functions ==--
--===============================--
	
	Vasa_CustomT = {}
	
	function CalculateHP(t)
		local incomingheals = UnitGetIncomingHeals(t) and UnitGetIncomingHeals(t) or 0
		local PercentWithIncoming = 100 * ( UnitHealth(t) + incomingheals ) / UnitHealthMax(t)
		local ActualWithIncoming = ( UnitHealthMax(t) - ( UnitHealth(t) + incomingheals ) )
		if PercentWithIncoming and ActualWithIncoming then
			return PercentWithIncoming, ActualWithIncoming
		else
			return 100,UnitHealthMax("player")
		end
	end
	
	function CalculateShieldHP(t)
		local incomingheals = 0
		local CurShield = select(15,UnitDebuffID(t, 142863)) or select(15,UnitDebuffID(t, 142864)) or select(15,UnitDebuffID(t, 142865)) or (UnitHealthMax(t) / 2)
		local PercentWithIncoming = 100 * ( CurShield + incomingheals ) / UnitHealthMax(t)
		local ActualWithIncoming = ( UnitHealthMax(t) - ( CurShield + incomingheals ) )
		if PercentWithIncoming and ActualWithIncoming then
			return PercentWithIncoming, ActualWithIncoming
		else
			return 100,UnitHealthMax("player")
		end
	end
	
	function CanHeal(t)
		if not UnitIsCharmed(t)
		and (UnitInRange(t) or not UnitIsPlayer(t))
		and UnitIsConnected(t)
		and (UnitCanCooperate("player",t) or not UnitIsPlayer(t))
		and not UnitIsDeadOrGhost(t)
		and CanHealEvents(t)
		then
			return true
		else
			return false
		end
	end
	
	function CanHealEvents(t)
		-- 4xEventsCheck
		if UnitDebuffID(t,104451) -- Ice Tomb - Hagara the Stormbinder
		or UnitDebuffID(t,23402) -- Corrupted Healing - DS
		-- 53EventsCheck
		or UnitDebuffID(t,121949) -- Parasistic Growth - Amber-Shaper Un'sok
		or UnitDebuffID(t,122784) -- Reshape Life - Amber-Shaper Un'sok
		or UnitDebuffID(t,122370) -- Reshape Life 2 - Amber-Shaper Un'sok
		or UnitDebuffID(t,123184) -- Dissonance Field
		or UnitDebuffID(t,123255) -- Dissonance Field 2
		or UnitDebuffID(t,123596) -- Dissonance Field 3
		or UnitDebuffID(t,128353) -- Dissonance Field 4
		or UnitDebuffID(t,128353) -- Dissonance Field 4
		or UnitDebuffID(t,137341) -- Beast of Nightmares
		or UnitDebuffID(t,137360) -- Corrupted Healing - ToT
		or UnitDebuffID(t,140701) -- Crystal Shell: Full Capacity! - Tortos HC - break SpiritShell
		-- 54EventsCheck
		or (UnitDebuffID(t, 142861) and UnitDebuffID(t, 142865)) -- Malkorok: Ancient Miasma and Strong Ancient Barrier
		then
			return false
		else
			return true
		end
	end
	
function SheuronEngine(MO, LOWHP, ACTUALHP, TARGETHEAL, SPECIALNPCS, HEALPET)
	tanks = { }
	Queue_Sys = { }
	local MouseoverCheck = MO or false
	local ActualHP = ACTUALHP or false
	local LowHPTarget = LOWHP or 80
	local TargetHealCheck = TARGETHEAL or false
	local SPECIALNPCS = SPECIALNPCS or false
	local HEALPET = HEALPET or true
	local ASP = UnitGetTotalAbsorbs("player") or 0
	lowhpmembers = 0
	
	members = { { Unit = "player", HP = CalculateHP("player"), GUID = UnitGUID("player"), AHP = select(2, CalculateHP("player")), IsNPC = false, ASP = ASP } } 
	
	if SPECIALNPCS then
		if UnitDebuffID("player",145206) then --Aqua Bomb - Proving Grounds
			table.insert(Queue_Sys, { Unit = "player", HP = CalculateHP("player"), AHP = select(2, CalculateHP("player")), Type = 1, DebuffID = 145206, Stacks = 1, IsNPC = false, SpellType = 1 } )
		end
	end
	
	-- Check if the Player is apart of the Custom Table
	if #Vasa_CustomT > 0 then
		for i=1, #Vasa_CustomT do
			if UnitGUID("player") == Vasa_CustomT[i].GUID then
				Vasa_CustomT[i].Unit = "player"
				Vasa_CustomT[i].HP = CalculateHP("player")
				Vasa_CustomT[i].AHP = select(2, CalculateHP("player"))
				Vasa_CustomT[i].IsNPC = false
				Vasa_CustomT[i].ASP = ASP
			end
		end
	end
	
	if IsInRaid() then
			group = "raid"
	elseif IsInGroup() then
			group = "party"
	end
	
	for i = 1, GetNumGroupMembers() do
		local member, memberhp, memberahp, uidmember = group..i, CalculateHP(group..i), select(2, CalculateHP(group..i)), UnitGUID(group..i)
		local memberasp = UnitGetTotalAbsorbs(group..i) or 0
		-- Checking all Party/Raid Members for Range/Health
		if ((UnitExists(member) and CanHeal(member)) or UnitIsUnit("player",member))
		and member ~= nil and memberhp ~= nil and memberahp ~= nil and uidmember ~= nil then
			-- Checking if Member has threat
			if UnitThreatSituation(member) == 3 then memberhp = memberhp - 1 end
			-- Checking if Member is a tank
			if UnitGroupRolesAssigned(member) == "TANK" then
				memberhp = memberhp - 1
				table.insert(tanks, { Unit = member, HP = memberhp, AHP = memberahp, IsNPC = false, ASP = memberasp } )
			end
			
			--Special NPCs
			if SPECIALNPCS then
				local npcid = tonumber(UnitGUID(member):sub(23,27),10)
				if UnitDebuffID(member,145263) then --Chomp debuff - Proving Grounds
					memberhp = memberhp - 20
				end
				if UnitDebuffID(member,145206) or UnitDebuffID(member,139375) or UnitDebuffID(member,139966) then --Aqua Bomb - Proving Grounds, Shadow Burst & Debilitate - Legendary quest					
					memberhp = memberhp - 5
					if npcid == 0 then
						local IsNPC = false
					else
						local IsNPC = true
					end
					table.insert(Queue_Sys, { Unit = member, HP = memberhp, AHP = memberahp, Type = 1, DebuffID = 145206, Stacks = 1, IsNPC = IsNPC, SpellType = 1 } )
					--VAS_WriteToChat("\124cFFFF55FFUnitName: "..UnitName(member))
				end
				if npcid == 72218 or npcid == 69837 then --Oto the Protector - Proving Grounds
					memberhp = memberhp - 1
					table.insert(tanks, { Unit = member, HP = memberhp, AHP = memberahp, IsNPC = true, ASP = memberasp } )
					--VAS_WriteToChat("\124cFFFF55FF1111111111")
				end
			end
			
			-- If they are in the Custom Table add their info in
			if #Vasa_CustomT > 0 then
				for i=1, #Vasa_CustomT do
					if uidmember == Vasa_CustomT[i].GUID then
						Vasa_CustomT[i].Unit = member
						Vasa_CustomT[i].HP = memberhp
						Vasa_CustomT[i].AHP = memberahp
						Vasa_CustomT[i].IsNPC = false
						Vasa_CustomT[i].ASP = memberasp
					end
				end
			end
			
			table.insert( members,{ Unit = member, HP = memberhp, GUID = uidmember, AHP = memberahp, IsNPC = false, ASP = memberasp } )
			
			-- Setting Low HP Members variable for AoE Healing
			if not ActualHP and memberhp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			elseif ActualHP and memberahp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			end
		end
		
		-- Checking Pets in the group
		if HEALPET and UnitExists(group..i.."pet") and CanHeal(group..i.."pet") then
			local memberpet, memberpethp, memberpetahp, uidmemberpet, memberpetASP = nil, nil, nil, nil, nil
			if UnitAffectingCombat("player") then
				 memberpet = group..i.."pet"
				 memberpethp = CalculateHP(memberpet) * 2
				 memberpetahp = select(2, CalculateHP(memberpet))
				 uidmemberpet = UnitGUID(memberpet)
				 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
			else
				 memberpet = group..i.."pet"
				 memberpethp = CalculateHP(memberpet)
				 memberpetahp = select(2, CalculateHP(memberpet))
				 uidmemberpet = UnitGUID(memberpet)
				 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
			end
			
			-- Checking if Pet is apart of the CustomTable
			if #Vasa_CustomT > 0 then
				for i=1, #Vasa_CustomT do
					if uidmemberpet == Vasa_CustomT[i].GUID then
						Vasa_CustomT[i].Unit = memberpet 
						Vasa_CustomT[i].HP = memberpethp
						Vasa_CustomT[i].AHP = memberpetahp
						Vasa_CustomT[i].IsNPC = false
						Vasa_CustomT[i].ASP = memberpetASP
					end
				end
			end
			if memberpet ~= nil and memberpethp ~= nil and uidmemberpet ~= nil and memberpetahp ~= nil then
				table.insert(members, { Unit = memberpet, HP = memberpethp, GUID = uidmemberpet, AHP = memberpetahp, IsNPC = false, ASP = memberpetASP } )
			end
			-- Setting Low HP Members variable for AoE Healing
			if not ActualHP and memberpethp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			elseif ActualHP and memberpetahp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			end
		end
		
	end 
	
	--Bad Debuffs
	if #Queue_Sys > 0 then
		table.sort(Queue_Sys, function(x,y) return x.Stacks > y.Stacks end)
	end
	
	-- So if we pass that ActualHP is true, then we will sort by most health missing. If not, we sort by lowest % of health.
	if not ActualHP then
		table.sort(members, function(x,y) return x.HP < y.HP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.HP < y.HP end)
		end
	elseif ActualHP then
		table.sort(members, function(x,y) return x.AHP > y.AHP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.AHP > y.AHP end)
		end
	end
	
	-- Checking Priority Targeting
	local T_heal = TargetHealCheck and CanHeal("target") and "target"
	local M_heal = MouseoverCheck and CanHeal("mouseover") and GetMouseFocus() ~= WorldFrame and "mouseover"
	if T_heal then
		table.sort(members, function(x) return UnitIsUnit(T_heal,x.Unit) end)
	elseif M_heal then
		table.sort(members, function(x) return UnitIsUnit(M_heal,x.Unit) end)
	end
end

function ShieldSheuronEngine(MO, LOWHP, ACTUALHP, TARGETHEAL, HEALPET)
	tanks = { }
	local MouseoverCheck = MO or false
	local ActualHP = ACTUALHP or false
	local LowHPTarget = LOWHP or 80
	local TargetHealCheck = TARGETHEAL or false
	local HEALPET = HEALPET or true
	local ASP = UnitGetTotalAbsorbs("player") or 0
	lowhpmembers = 0
	
	members = { { Unit = "player", HP = CalculateShieldHP("player"), GUID = UnitGUID("player"), AHP = select(2, CalculateShieldHP("player")), IsNPC = false, ASP = ASP } } 
	
	-- Check if the Player is apart of the Custom Table
	if #Vasa_CustomT > 0 then
		for i=1, #Vasa_CustomT do
			if UnitGUID("player") == Vasa_CustomT[i].GUID then
				Vasa_CustomT[i].Unit = "player"
				Vasa_CustomT[i].HP = CalculateShieldHP("player")
				Vasa_CustomT[i].AHP = select(2, CalculateShieldHP("player"))
				Vasa_CustomT[i].IsNPC = false
				Vasa_CustomT[i].ASP = ASP
			end
		end
	end
	
	if IsInRaid() then
			group = "raid"
	elseif IsInGroup() then
			group = "party"
	end
	
	for i = 1, GetNumGroupMembers() do
		local member, memberhp, memberahp, uidmember = group..i, CalculateShieldHP(group..i), select(2, CalculateShieldHP(group..i)), UnitGUID(group..i)	
		local memberasp = UnitGetTotalAbsorbs(group..i) or 0
		
		-- Checking all Party/Raid Members for Range/Health
		if (UnitExists(member) and CanHeal(member)) or UnitIsUnit("player",member) then
			-- Checking if Member has threat
			if UnitThreatSituation(member) == 3 then memberhp = memberhp - 1 end
			-- Checking if Member is a tank
			if UnitGroupRolesAssigned(member) == "TANK" then
				memberhp = memberhp - 1
				if member ~= nil and memberhp ~= nil and memberahp ~= nil then
					table.insert(tanks, { Unit = member, HP = memberhp, AHP = memberahp, IsNPC = false, ASP = memberasp } )
				end
			end
			
			-- If they are in the Custom Table add their info in
			if #Vasa_CustomT > 0 then
				for i=1, #Vasa_CustomT do
					if uidmember == Vasa_CustomT[i].GUID then
						Vasa_CustomT[i].Unit = member
						Vasa_CustomT[i].HP = memberhp
						Vasa_CustomT[i].AHP = memberahp
						Vasa_CustomT[i].IsNPC = false
						Vasa_CustomT[i].ASP = memberasp
					end
				end
			end
			if member ~= nil and memberhp ~= nil and uidmember ~= nil and memberahp ~= nil then
				table.insert( members,{ Unit = member, HP = memberhp, GUID = uidmember, AHP = memberahp, IsNPC = false, ASP = memberasp } )
			end
			-- Setting Low HP Members variable for AoE Healing
			if not ActualHP and memberhp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			elseif ActualHP and memberahp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			end
		end
		
		-- Checking Pets in the group
		if HEALPET and UnitExists(group..i.."pet") and CanHeal(group..i.."pet") then
			local memberpet, memberpethp, memberpetahp, uidmemberpet, memberpetASP = nil, nil, nil, nil, nil
			if UnitAffectingCombat("player") then
				 memberpet = group..i.."pet"
				 memberpethp = CalculateShieldHP(memberpet) * 2
				 memberpetahp = select(2, CalculateShieldHP(memberpet))
				 uidmemberpet = UnitGUID(memberpet)
				 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
			else
				 memberpet = group..i.."pet"
				 memberpethp = CalculateShieldHP(memberpet)
				 memberpetahp = select(2, CalculateShieldHP(memberpet))
				 uidmemberpet = UnitGUID(memberpet)
				 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
			end
			
			-- Checking if Pet is apart of the CustomTable
			if #Vasa_CustomT > 0 then
				for i=1, #Vasa_CustomT do
					if uidmemberpet == Vasa_CustomT[i].GUID then
						Vasa_CustomT[i].Unit = memberpet
						Vasa_CustomT[i].HP = memberpethp
						Vasa_CustomT[i].AHP = memberpetahp
						Vasa_CustomT[i].IsNPC = false
						Vasa_CustomT[i].ASP = memberpetASP
					end
				end
			end
			if memberpet ~= nil and memberpethp ~= nil and uidmemberpet ~= nil and memberpetahp ~= nil then
				table.insert(members, { Unit = memberpet, HP = memberpethp, GUID = uidmemberpet, AHP = memberpetahp, IsNPC = false, ASP = memberpetASP } )
			end
			-- Setting Low HP Members variable for AoE Healing
			if not ActualHP and memberpethp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			elseif ActualHP and memberpetahp < LowHPTarget then
				lowhpmembers = lowhpmembers + 1
			end
		end
	end
	
	--Bad Debuffs
	if #Queue_Sys > 0 then
		table.sort(Queue_Sys, function(x,y) return x.Stacks > y.Stacks end)
	end
	
	-- So if we pass that ActualHP is true, then we will sort by most health missing. If not, we sort by lowest % of health.
	if not ActualHP then
		table.sort(members, function(x,y) return x.HP < y.HP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.HP < y.HP end)
		end
	elseif ActualHP then
		table.sort(members, function(x,y) return x.AHP > y.AHP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.AHP > y.AHP end)
		end
	end
	
	-- Checking Priority Targeting
	if TargetHealCheck and CanHeal("target") then
		table.sort(members, function(x) return UnitIsUnit("target",x.Unit) end)
	elseif MouseoverCheck and CanHeal("mouseover") and GetMouseFocus() ~= WorldFrame then
		table.sort(members, function(x) return UnitIsUnit("mouseover",x.Unit) end)
	end
end

function BossSheuronEngine(MO, LOWHP, ACTUALHP, TARGETHEAL, BOSSTOTAL, ONLYBOSSANDHEALER, SPELLID)
	tanks = { }
	local MouseoverCheck = MO or false
	local ActualHP = ACTUALHP or false
	local LowHPTarget = LOWHP or 80
	local TargetHealCheck = TARGETHEAL or false
	local BOSSTOTAL = BOSSTOTAL or 1
	local ONLYBOSSANDHEALER = ONLYBOSSANDHEALER or false
	local SPELLID = SPELLID or 83968 --mass rez
	local ASP = UnitGetTotalAbsorbs("player") or 0
	lowhpmembers = 0
	
	members = { { Unit = "player", HP = CalculateHP("player"), GUID = UnitGUID("player"), AHP = select(2, CalculateHP("player")), IsNPC = false, ASP = ASP } } 
	
	-- Check if the Player is apart of the Custom Table
	for i=1, #Vasa_CustomT do
		if UnitGUID("player") == Vasa_CustomT[i].GUID then 
			Vasa_CustomT[i].Unit = "player"
			Vasa_CustomT[i].HP = CalculateHP("player")
			Vasa_CustomT[i].AHP = select(2, CalculateHP("player"))
			Vasa_CustomT[i].IsNPC = false
			Vasa_CustomT[i].ASP = ASP
		end
	end
	
	if IsInRaid() then
			group = "raid"
	elseif IsInGroup() then
			group = "party"
	end
	
	for i = 1, BOSSTOTAL do
	    local boss,bosshp, bossasp = "boss"..i, CalculateHP("boss"..i), UnitGetTotalAbsorbs("boss") or 0
	    if IsSpellInRange(GetSpellInfo(SPELLID),boss)
	    then
	    	if boss ~= nil and bosshp ~= nil and UnitGUID(boss) ~= nil and select(2, CalculateHP(boss)) ~= nil then
				table.insert( members,{ Unit = boss, HP = bosshp, GUID = UnitGUID(boss), AHP = select(2, CalculateHP(boss)), IsNPC = true, ASP = bossasp } ) 
			end
	    end
	end
	
	if not ONLYBOSSANDHEALER then
		for i = 1, GetNumGroupMembers() do
			local member, memberhp, memberasp = group..i, CalculateHP(group..i), UnitGetTotalAbsorbs(group..i) or 0
			
			-- Checking all Party/Raid Members for Range/Health
			if CanHeal(member) then
				-- Checking if Member has threat
				if UnitThreatSituation(member) == 3 then memberhp = memberhp - 1 end
				-- Checking if Member is a tank
				if UnitGroupRolesAssigned(member) == "TANK" then
					memberhp = memberhp - 1
					if member ~= nil and memberhp ~= nil and select(2, CalculateHP(member)) ~= nil then
						table.insert(tanks, { Unit = member, HP = memberhp, AHP = select(2, CalculateHP(member)), IsNPC = false, ASP = memberasp } )
					end
				end
				-- If they are in the Custom Table add their info in
				for i=1, #Vasa_CustomT do 
					if UnitGUID(member) == Vasa_CustomT[i].GUID then
						Vasa_CustomT[i].Unit = member
						Vasa_CustomT[i].HP = memberhp
						Vasa_CustomT[i].AHP = select(2, CalculateHP(member))
						Vasa_CustomT[i].IsNPC = false
						Vasa_CustomT[i].ASP = memberasp
					end
				end
				if group..i ~= nil and memberhp ~= nil and UnitGUID(group..i) ~= nil and select(2, CalculateHP(group..i)) ~= nil then
					table.insert( members,{ Unit = group..i, HP = memberhp, GUID = UnitGUID(group..i), AHP = select(2, CalculateHP(group..i)), IsNPC = false, ASP = memberasp } ) 
				end
			end
			
			-- Checking Pets in the group
			if HEALPET and UnitExists(group..i.."pet") and CanHeal(group..i.."pet") then
				local memberpet, memberpethp, memberpetahp, uidmemberpet, memberpetASP = nil, nil, nil, nil, nil
				if UnitAffectingCombat("player") then
					 memberpet = group..i.."pet"
					 memberpethp = CalculateHP(memberpet) * 2
					 memberpetahp = select(2, CalculateHP(memberpet))
					 uidmemberpet = UnitGUID(memberpet)
					 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
				else
					 memberpet = group..i.."pet"
					 memberpethp = CalculateHP(memberpet)
					 memberpetahp = select(2, CalculateHP(memberpet))
					 uidmemberpet = UnitGUID(memberpet)
					 memberpetASP = UnitGetTotalAbsorbs(memberpet) or 0
				end
				
				-- Checking if Pet is apart of the CustomTable
				if #Vasa_CustomT > 0 then
					for i=1, #Vasa_CustomT do
						if uidmemberpet == Vasa_CustomT[i].GUID then
							Vasa_CustomT[i].Unit = memberpet
							Vasa_CustomT[i].HP = memberpethp
							Vasa_CustomT[i].AHP = memberpetahp
							Vasa_CustomT[i].IsNPC = false
							Vasa_CustomT[i].ASP = memberpetASP
						end
					end
				end
				if memberpet ~= nil and memberpethp ~= nil and uidmemberpet ~= nil and memberpetahp ~= nil then
					table.insert(members, { Unit = memberpet, HP = memberpethp, GUID = uidmemberpet, AHP = memberpetahp, IsNPC = false, ASP = memberpetASP } )
				end
			end
		end
	end
	
	-- So if we pass that ActualHP is true, then we will sort by most health missing. If not, we sort by lowest % of health.
	if not ActualHP then
		table.sort(members, function(x,y) return x.HP < y.HP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.HP < y.HP end)
		end
	elseif ActualHP then
		table.sort(members, function(x,y) return x.AHP > y.AHP end)
		if #tanks > 0 then
			table.sort(tanks, function(x,y) return x.AHP > y.AHP end)
		end
	end
	
	-- Setting Low HP Members variable for AoE Healing
	for i=1,#members do
		if members[i].HP < LowHPTarget then
			lowhpmembers = lowhpmembers + 1
		end
	end
	
	-- Checking Priority Targeting
	if (CanHeal("target") or (IsSpellInRange(GetSpellInfo(SPELLID),"target") and not UnitIsPlayer("target"))) and TargetHealCheck then
		table.sort(members, function(x) return UnitIsUnit("target",x.Unit) end)
	elseif (CanHeal("mouseover") or (IsSpellInRange(GetSpellInfo(SPELLID),"mouseover") and not UnitIsPlayer("mouseover"))) and GetMouseFocus() ~= WorldFrame and MouseoverCheck then
		table.sort(members, function(x) return UnitIsUnit("mouseover",x.Unit) end)
	end
end

--===========--
--== Other ==--
--===========--
	
	function GetEnemyCount()
		local count = 0
		local frames = {WorldFrame:GetChildren()}
		for _, frame in pairs(frames) do
			if frame:GetName() and frame:GetName():find('NamePlate%d') then
				if frame:IsShown() then
					count = count + 1
				end
			end
		end
		return count
	end
	
	DispelValidation = nil
	function DispelValidation(t)
		
		local HasValidDispel = false
		local i = 1
		local debuff = UnitDebuff(t, i)
		
		while debuff do
			
			local debuffType = select(5, UnitDebuff(t, i))
			
			if debuffType == "Poison"
			or debuffType == "Disease"
			or (debuffType == "Magic" and MistWeaver)
			then
				HasValidDispel = true
			end
			
			i = i + 1
			debuff = UnitDebuff(t, i)
			
		end
		
		return HasValidDispel
		
	end
	
	CobraShotCount = 0
	SpellCastChecks = CreateFrame("FRAME");
	SpellCastChecks:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
	SpellCastChecks:SetScript("OnEvent", function(self, event, ...)
		
	--	local timestamp, type, hideCaster,									-- arg1  to arg3
	--	sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags,	-- arg4  to arg11
	--	spellId, spellName, spellSchool,									-- arg12 to arg14
	--	amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...		-- arg15 to arg23
		
		if event == "COMBAT_LOG_EVENT_UNFILTERED" then
				
			if select(2, ...) == "SPELL_CAST_SUCCESS" then
				
				if select(12, ...) == 77767 then
					CobraShotCount = CobraShotCount + 1
				else
					if select(4, ...) == UnitGUID("player") then CobraShotCount = 0 end
				end
				
			end
		
		end
		
	end);
	
	LoSTable = nil
	LoSTable = { }
	IsLineOfSight = nil
	function IsLineOfSight(targetCheck, time)
		local time=time or 3
		targetGUID = UnitGUID(targetCheck) or 0
		
		for i=1, #LoSTable do
			if time < (GetTime() - LoSTable[i].time) then
 				table.remove(LoSTable, i)
				break
			end
		end
		
		function LoSCheck(self, event, ...)
			local targetGUID = targetGUID
			local Log = {...}
			local AlreadyTabled = false
			if Log[2] and Log[2] == "SPELL_CAST_FAILED" and targetGUID then
			
				if Log[4] and Log[4]==UnitGUID("player") then
					if Log[15] and Log[15]==SPELL_FAILED_LINE_OF_SIGHT
					or Log[15] and Log[15]==SPELL_FAILED_NOT_INFRONT
					or Log[15] and Log[15]==SPELL_FAILED_OUT_OF_RANGE
					or Log[15] and Log[15]==SPELL_FAILED_UNIT_NOT_INFRONT
					or Log[15] and Log[15]==SPELL_FAILED_UNIT_NOT_BEHIND
					or Log[15] and Log[15]==SPELL_FAILED_NOT_BEHIND
					or Log[15] and Log[15]==SPELL_FAILED_MOVING
					or Log[15] and Log[15]==SPELL_FAILED_IMMUNE
					or Log[15] and Log[15]==SPELL_FAILED_FLEEING
					or Log[15] and Log[15]==SPELL_FAILED_BAD_TARGETS
					or Log[15] and Log[15]==SPELL_FAILED_NO_MOUNTS_ALLOWED
					or Log[15] and Log[15]==SPELL_FAILED_STUNNED
					or Log[15] and Log[15]==SPELL_FAILED_SILENCED
					or Log[15] and Log[15]==SPELL_FAILED_NOT_IN_CONTROL
					or Log[15] and Log[15]==SPELL_FAILED_VISION_OBSCURED
					or Log[15] and Log[15]==SPELL_FAILED_DAMAGE_IMMUNE
					or Log[15] and Log[15]==SPELL_FAILED_CHARMED
					then
						for j=1, #LoSTable do
							if targetGUID == LoSTable[j].unit then
								AlreadyTabled = true
								break
							end
						end
						if not AlreadyTabled then
							table.insert(LoSTable, { unit=targetGUID, time=GetTime() } )
							targetGUID = nil
							_G.NovaLineOfSight:UnregisterAllEvents()
						end
					end
				end
			end
		end
    		
    		if not NovaLineOfSight then
			frameLOS = CreateFrame("frame", "NovaLineOfSight")
			frameLOS:SetScript("OnEvent", LoSCheck)
		end
		
		for k=1, #LoSTable do
			if targetGUID and targetGUID == LoSTable[k].unit then
				return false
			end
		end
		
		_G.NovaLineOfSight:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		return true
		
	end